#include <benchmark/benchmark.h>
#include "math.h"
#include "util.h"

#define PI 3.14159265
using namespace std;

static void Bm_function_Copysignl(benchmark::State &state)
{
    long double x = 2417851639229258349412352.000000;
    long double y = 6051711999279104.000000;
    for (auto _ : state)
    {
        // x为结果，y为符号
        benchmark::DoNotOptimize(copysignl(x, y));
    }

    // 打印在迭代次数里每秒处理的字节数
    state.SetItemsProcessed(state.iterations());
}

// 取余
static void Bm_function_Fmodl(benchmark::State &state)
{
    long double x = 6051711999279104.000000;
    long double y = 536870912.000000;
    for (auto _ : state)
    {
        benchmark::DoNotOptimize(fmodl(x, y));
    }
    state.SetItemsProcessed(state.iterations());
}

// 3.14的3.18次幂
static void Bm_function_Powf(benchmark::State &state)
{
    float x = 3.14;
    float y = 3.18;
    for (auto _ : state)
    {
        benchmark::DoNotOptimize(powf(x, y));
    }
    state.SetItemsProcessed(state.iterations());
}

// e的3.14次幂
static void Bm_function_Exp(benchmark::State &state)
{
    double x = 3.14;
    for (auto _ : state)
    {
        benchmark::DoNotOptimize(exp(x));
    }
    state.SetItemsProcessed(state.iterations());
}

// 基数为e，x的对数
static void Bm_function_Log(benchmark::State &state)
{

    double x = 3.14;

    for (auto _ : state)
    {
        benchmark::DoNotOptimize(log(x));
    }
    state.SetItemsProcessed(state.iterations());
}

static void Bm_function_Cos(benchmark::State &state)
{
    double x = 6.302892;
    double val = PI / 180.0;

    for (auto _ : state)
    {
        benchmark::DoNotOptimize(cos(x * val));
    }
    state.SetItemsProcessed(state.iterations());
}

// 将浮点数分解为尾数与指数
static void Bm_function_Frexpl(benchmark::State &state)
{
    long double x = 1024.0020;
    int e;
    for (auto _ : state)
    {
        benchmark::DoNotOptimize(frexpl(x, &e));
    }
    state.SetItemsProcessed(state.iterations());
}

// x * 2 ^ n
static void Bm_function_Scalbn(benchmark::State &state)
{
    double x = 3.8;
    int n = 8;
    for (auto _ : state)
    {
        benchmark::DoNotOptimize(scalbn(x, n));
    }
    state.SetItemsProcessed(state.iterations());
}

// x * 2 ^ n
static void Bm_function_Scalbnl(benchmark::State &state)
{
    long double x = (long double)2e-10;
    int n = 10;

    for (auto _ : state)
    {
        benchmark::DoNotOptimize(scalbnl(x, n));
    }
    state.SetItemsProcessed(state.iterations());
}

static void Bm_function_Fmod(benchmark::State &state)
{
    double x = 10.5;
    double y = 3.2;
    for (auto _ : state)
    {
        benchmark::DoNotOptimize(fmod(x, y));
    }
    state.SetItemsProcessed(state.iterations());
}

static void Bm_function_sin(benchmark::State &state)
{
    double x = 45.0;
    double val = PI / 180.0;

    for (auto _ : state)
    {
        benchmark::DoNotOptimize(sin(x*val));
    }
    state.SetItemsProcessed(state.iterations());
} 

MUSL_BENCHMARK(Bm_function_Copysignl);
MUSL_BENCHMARK(Bm_function_Fmodl);
MUSL_BENCHMARK(Bm_function_Powf);
MUSL_BENCHMARK(Bm_function_Exp);
MUSL_BENCHMARK(Bm_function_Log);
MUSL_BENCHMARK(Bm_function_Cos);
MUSL_BENCHMARK(Bm_function_Frexpl);
MUSL_BENCHMARK(Bm_function_Scalbn);
MUSL_BENCHMARK(Bm_function_Scalbnl);
MUSL_BENCHMARK(Bm_function_Fmod);
MUSL_BENCHMARK(Bm_function_sin);